--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
scripts/ci/android-emulator-smoke.sh c0b0ddffd735a0d007c1be9a5e8563ec42fdafc0 (c0b0ddff) Text, 4.63 KB
T8b949e#!/usr/bin/env bash
T8b949e# Install a MeshChatX APK on a running emulator/device, launch MainActivity,
T8b949e# and fail if the Chaquopy backend does not become healthy.
T8b949e#
T8b949e# Expects: adb on PATH, one device/emulator online, APK path as $1 or MESHCHATX_APK.
Tffa657set -euo pipefail
Te6edf3PACKAGETff7b72=Ta5d6ff"Tffd700${Te6edf3MESHCHATX_ANDROID_PACKAGETff7b72:-Te6edf3comTb4b4b4.meshchatxTffd700}Ta5d6ff"
Te6edf3ACTIVITYTff7b72=Ta5d6ff"Tffd700${Te6edf3MESHCHATX_ANDROID_ACTIVITYTff7b72:-Te6edf3comTb4b4b4.meshchatx/.MainActivityTffd700}Ta5d6ff"
Te6edf3STATUS_PATHTff7b72=Ta5d6ff"Tffd700${Te6edf3MESHCHATX_SMOKE_STATUS_PATHTff7b72:-Tb4b4b4/api/v1/statusTffd700}Ta5d6ff"
Te6edf3TIMEOUT_SECTff7b72=Ta5d6ff"Tffd700${Te6edf3MESHCHATX_SMOKE_TIMEOUT_SECTff7b72:-Te6edf3180Tffd700}Ta5d6ff"
Te6edf3LOGCAT_TAG_FILTERTff7b72=Ta5d6ff"Tffd700${Te6edf3MESHCHATX_SMOKE_LOGCAT_FILTERTff7b72:-Te6edf3PythonTb4b4b4|meshchat|MeshChat|chaquo|AndroidRuntimeTffd700}Ta5d6ff"
Te6edf3APKTff7b72=Ta5d6ff"Tffd700${Te6edf31Tff7b72:-Tffd700${Te6edf3MESHCHATX_APKTff7b72:-Tffd700}Tffd700}Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3APKTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffusage: Te6edf3$0Ta5d6ff <path-to.apk>Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff2
Tff7b72fi
Tff7b72if Tff7b72[Tff7b72[ ! -f Ta5d6ff"Tffd700${Te6edf3APKTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffAPK not found: Tffd700${Te6edf3APKTffd700}Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff2
Tff7b72fi
Tff7b72if ! Tffa657command -v adb >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"adb not found on PATH" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff2
Tff7b72fi
adb wait-for-device
Te6edf3deadlineTff7b72=Tff7b72$((Te6edf3SECONDS Tff7b72+ T79c0ff120Tff7b72))
Tff7b72until adb shell getprop sys.boot_completed T79c0ff2>/dev/null Tb4b4b4| tr -d Ta5d6ff'\r' Tb4b4b4| grep -qx Ta5d6ff'1'Tb4b4b4; Tff7b72do
Tff7b72if Tff7b72(Tff7b72( SECONDS >Tff7b72= deadline Tff7b72)Tff7b72)Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"emulator did not finish booting within 120s" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
sleep T79c0ff2
Tff7b72done
Tffa657echo Ta5d6ff"Ta5d6ffInstalling Tffd700${Te6edf3APKTffd700}Ta5d6ff"
adb install -r -t --no-incremental Ta5d6ff"Tffd700${Te6edf3APKTffd700}Ta5d6ff"
Tffa657echo Ta5d6ff"Ta5d6ffClearing logcat and launching Tffd700${Te6edf3ACTIVITYTffd700}Ta5d6ff"
adb logcat -c Tff7b72|| Tffa657true
adb shell am force-stop Ta5d6ff"Tffd700${Te6edf3PACKAGETffd700}Ta5d6ff" Tff7b72|| Tffa657true
adb shell am start -W -n Ta5d6ff"Tffd700${Te6edf3ACTIVITYTffd700}Ta5d6ff"
Te6edf3workdirTff7b72=Ta5d6ff"Tff7b72$(mktemp -d Ta5d6ff"Tffd700${Te6edf3TMPDIRTff7b72:-Tb4b4b4/tmpTffd700}Ta5d6ff/meshchatx-android-smoke.XXXXXXTa5d6ff"Tff7b72)Ta5d6ff"
Tffa657trap Ta5d6ff'rm -rf "${workdir}"' EXIT
Te6edf3logcat_fileTff7b72=Ta5d6ff"Tffd700${Te6edf3workdirTffd700}Ta5d6ff/logcat.txtTa5d6ff"
adb logcat -v Tffa657time >Ta5d6ff"Tffd700${Te6edf3logcat_fileTffd700}Ta5d6ff" Tb4b4b4&
Te6edf3logcat_pidTff7b72=Te6edf3$!
cleanup_logcatTff7b72(Tff7b72) Tff7b72{
Tffa657kill Ta5d6ff"Tffd700${Te6edf3logcat_pidTffd700}Ta5d6ff" >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1 Tff7b72|| Tffa657true
Tffa657wait Ta5d6ff"Tffd700${Te6edf3logcat_pidTffd700}Ta5d6ff" >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1 Tff7b72|| Tffa657true
Tff7b72}
Tffa657trap Ta5d6ff'cleanup_logcat; rm -rf "${workdir}"' EXIT
fail_with_logsTff7b72(Tff7b72) Tff7b72{
Tffa657local Te6edf3reasonTff7b72=Ta5d6ff"Te6edf3$1Ta5d6ff"
Tffa657echo Ta5d6ff"Ta5d6ff::error::Android emulator smoke failed: Tffd700${Te6edf3reasonTffd700}Ta5d6ff"
Tffa657echo Ta5d6ff"---- logcat (filtered) ----"
grep -E Ta5d6ff"Tffd700${Te6edf3LOGCAT_TAG_FILTERTffd700}Ta5d6ff|PyException|SystemExit|ModuleNotFoundError|StorageLock|backend failed|Error starting MeshChatXTa5d6ff" Tffea00\
Ta5d6ff"Tffd700${Te6edf3logcat_fileTffd700}Ta5d6ff" Tb4b4b4| tail -n T79c0ff200 Tff7b72|| Tffa657true
Tffa657echo Ta5d6ff"---- logcat (tail) ----"
tail -n T79c0ff120 Ta5d6ff"Tffd700${Te6edf3logcat_fileTffd700}Ta5d6ff" Tff7b72|| Tffa657true
Tffa657exit T79c0ff1
Tff7b72}
probe_status_okTff7b72(Tff7b72) Tff7b72{
T8b949e# Probe from inside the emulator (server binds 127.0.0.1 on-device).
T8b949e# Prefer toybox wget (API 30+ images); fall back to python if present.
Tffa657local Te6edf3bodyTff7b72=Ta5d6ff""
Tff7b72if adb shell Ta5d6ff"command -v wget >/dev/null 2>&1" >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Te6edf3bodyTff7b72=Ta5d6ff"Tff7b72$(adb shell Ta5d6ff"Ta5d6ffwget -qO- --no-check-certificate https://127.0.0.1:8000Tffd700${Te6edf3STATUS_PATHTffd700}Ta5d6ff" T79c0ff2>/dev/null Tb4b4b4| tr -d Ta5d6ff'\r' Tff7b72|| Tffa657trueTff7b72)Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3bodyTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3bodyTff7b72=Ta5d6ff"Tff7b72$(adb shell Ta5d6ff"Ta5d6ffwget -qO- http://127.0.0.1:8000Tffd700${Te6edf3STATUS_PATHTffd700}Ta5d6ff" T79c0ff2>/dev/null Tb4b4b4| tr -d Ta5d6ff'\r' Tff7b72|| Tffa657trueTff7b72)Ta5d6ff"
Tff7b72fi
Tff7b72elif adb shell Ta5d6ff"command -v curl >/dev/null 2>&1" >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Te6edf3bodyTff7b72=Ta5d6ff"Tff7b72$(adb shell Ta5d6ff"Ta5d6ffcurl -ksS --max-time 3 https://127.0.0.1:8000Tffd700${Te6edf3STATUS_PATHTffd700}Ta5d6ff" T79c0ff2>/dev/null Tb4b4b4| tr -d Ta5d6ff'\r' Tff7b72|| Tffa657trueTff7b72)Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3bodyTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3bodyTff7b72=Ta5d6ff"Tff7b72$(adb shell Ta5d6ff"Ta5d6ffcurl -fsS --max-time 3 http://127.0.0.1:8000Tffd700${Te6edf3STATUS_PATHTffd700}Ta5d6ff" T79c0ff2>/dev/null Tb4b4b4| tr -d Ta5d6ff'\r' Tff7b72|| Tffa657trueTff7b72)Ta5d6ff"
Tff7b72fi
Tff7b72else
T8b949e# Escape path for embedding in a double-quoted adb shell command.
Tffa657local py_path
Te6edf3py_pathTff7b72=Ta5d6ff"Tff7b72$(Tffa657printf Ta5d6ff'%s' Ta5d6ff"Tffd700${Te6edf3STATUS_PATHTffd700}Ta5d6ff" Tb4b4b4| sed Ta5d6ff's/\\/\\\\/g; s/"/\\"/g'Tff7b72)Ta5d6ff"
Te6edf3bodyTff7b72=Ta5d6ff"Tff7b72$(
adb shell Ta5d6ff"Ta5d6ffpython3 -c \"
import ssl, urllib.request
ctx = ssl._create_unverified_context()
urls = (
('https://127.0.0.1:8000Tffd700${Te6edf3py_pathTffd700}Ta5d6ff', ctx),
('http://127.0.0.1:8000Tffd700${Te6edf3py_pathTffd700}Ta5d6ff', None),
)
for url, context in urls:
try:
kwargs = {'timeout': 3}
if context is not None:
kwargs['context'] = context
print(urllib.request.urlopen(url, **kwargs).read().decode())
break
except Exception:
pass
\"Ta5d6ff" T79c0ff2>/dev/null Tb4b4b4| tr -d Ta5d6ff'\r' Tff7b72|| Tffa657true
Tff7b72)Ta5d6ff"
Tff7b72fi
Tffa657printf Ta5d6ff'%s' Ta5d6ff"Tffd700${Te6edf3bodyTffd700}Ta5d6ff" Tb4b4b4| grep -q Ta5d6ff'"status"[[:space:]]*:[[:space:]]*"ok"'
Tff7b72}
Tffa657echo Ta5d6ff"Ta5d6ffWaiting up to Tffd700${Te6edf3TIMEOUT_SECTffd700}Ta5d6ffs for backend health (Tffd700${Te6edf3STATUS_PATHTffd700}Ta5d6ff)Ta5d6ff"
Te6edf3deadlineTff7b72=Tff7b72$((Te6edf3SECONDS Tff7b72+ Te6edf3TIMEOUT_SECTff7b72))
Te6edf3healthyTff7b72=T79c0ff0
Tff7b72while Tff7b72(Tff7b72( SECONDS < deadline Tff7b72)Tff7b72)Tb4b4b4; Tff7b72do
Tff7b72if grep -Eiq Ta5d6ff'PyException|ModuleNotFoundError: No module named|SystemExit: 1|MeshChatX backend failed|Error starting MeshChatX server' Tffea00\
Ta5d6ff"Tffd700${Te6edf3logcat_fileTffd700}Ta5d6ff"Tb4b4b4; Tff7b72then
fail_with_logs Ta5d6ff"fatal backend error seen in logcat"
Tff7b72fi
Tff7b72if probe_status_okTb4b4b4; Tff7b72then
Te6edf3healthyTff7b72=T79c0ff1
Tff7b72break
Tff7b72fi
sleep T79c0ff3
Tff7b72done
Tff7b72if Tff7b72[Tff7b72[ Ta5d6ff"Tffd700${Te6edf3healthyTffd700}Ta5d6ff" -ne T79c0ff1 Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
fail_with_logs Ta5d6ff"Ta5d6ffbackend /api/v1/status did not become ok within Tffd700${Te6edf3TIMEOUT_SECTffd700}Ta5d6ffsTa5d6ff"
Tff7b72fi
Tffa657echo Ta5d6ff"Ta5d6ffAndroid emulator smoke OK: Tffd700${Te6edf3STATUS_PATHTffd700}Ta5d6ff returned status=okTa5d6ff"
grep -E Ta5d6ff"Tffd700${Te6edf3LOGCAT_TAG_FILTERTffd700}Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3logcat_fileTffd700}Ta5d6ff" Tb4b4b4| tail -n T79c0ff40 Tff7b72|| Tffa657true
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────